package com.nulldev.util.scripting.cup.vee;

import java.math.BigInteger;

public abstract class CUPRegister<T> {

	public static enum CUPRegisterType {
		SHORT(0x1), /* short */
		NORMAL(0x2), /* int */
		EXTENDED(0x3), /* long */
		WIDE(0x4), /* BigInteger */

		CUSTOM(0x5), /* ??? */

		/* Added in SIL, Revision 1 */

		STRING(0x6),
		FLOAT(0x7),
		FLOAT_SFP(0x8),
		DOUBLE(0x9)

		;

		private final short type;

		private CUPRegisterType(final int type) {
			this.type = (short) type;
		}

		public short getType() {
			return this.type;
		}
	}

	public abstract CUPRegisterType getRegisterType();

	public abstract T get();

	public abstract void set(final T value);

	public abstract void reset();

	public CUPRegister<T> setAndReturn(final T value) {
		this.set(value);
		return this;
	}

	public CUPRegister<T> lock() {
		return this;
	}

	public abstract boolean valuePresent();

	public abstract int getRegisterID();

	@Override
	public String toString() {
		return this.get() + ", " + this.getRegisterType();
	}

	public boolean isSameAs(final CUPRegister<?> regB) {
		return regB != null && regB.getRegisterType() == getRegisterType();
	}

	public boolean isSameType(final Object obj) {
		switch (getRegisterType()) {
			case SHORT:
				return obj instanceof Short;
			case NORMAL:
				return obj instanceof Integer || obj instanceof Short;
			case WIDE:
				return obj instanceof Long || obj instanceof Short || obj instanceof Integer;
			case EXTENDED:
				return obj instanceof BigInteger;
			case FLOAT:
			case FLOAT_SFP:
				return obj instanceof Float || obj instanceof Integer;
			case STRING:
				return obj instanceof String;
			case DOUBLE:
				return obj instanceof Double;
			case CUSTOM:
			default:
				return obj.getClass().isInstance(get());
		}
	}
}
